/* userPhyAccess.c */

/************************************************************************************
*                    Copyright Aquantia Corporation
*                              Freeware
*
* Description:
*
*   Supplies the base PHY register read and write functions that are 
*   called by the RPC Server functions.
*
************************************************************************************/

/*! \file
 * Supplies the base PHY register read and write functions that are 
 * called by the RPC Server functions. */

#include "userPhyAccess.h"
#include "stdlib.h"
#include "stdio.h"
#include "string.h"
#include "errno.h"
#include "stdbool.h"
#ifdef __cplusplus
  extern "C" {
#endif

/**
  * @brief 
  */
bool my_is_big_char(char ch)
{
	if(ch >= 'A' && ch <= 'F')
		return true;
	else
		return false;
}

bool my_is_small_char(char ch)
{
	if(ch >= 'a' && ch <= 'f')
		return true;
	else
		return false;
}
bool my_isdigit(char ch)
{
	if(ch >= '0' && ch <= '9') 
		return true;
	else
		return false;
}


/**
  * @brief
  * @example  1a -> 0x1a
  *           0X9B, -> 0x9b
  *           0xab 0xcd   --> 0xcdab
  */
int ascii2hex(char** q, int* ret_val)
{
	int hex = 0;
	int loop = 0;
	char* p = *q;

FILTER_STR:
	while((isdigit(*p) == false) && (my_is_big_char(*p) == false) && (my_is_small_char(*p) == false) && (*p != 0))
	{
		p++;
	}
	if(*p == 0)
	{
		*q = p; 
		return false;
	}

	do{	
		if(isdigit(*p))
		{

			if(((*p == '0') && (*(p+1) == 'x')) || ((*p == '0') && (*(p+1) == 'X'))) /* '0x' '0X' */
			{
				p += 2;
				goto FILTER_STR;	
			}	
			hex <<= 4;
			hex |=  (*p - '0');	               /* 0 1 2 3 4 5 6 7 8 9 */	
		}
		else if(my_is_big_char(*p))            /* A B C D E F */
		{
			hex <<= 4;
			hex |=  (*p - 'A') + 10;		
		}
		else if(my_is_small_char(*p))          /* a b c d e f */
		{
			hex <<= 4;
			hex |=  (*p - 'a') + 10;		
		}
		else
		{
			break;	
		}
		p++;
	}while(*p != 0); 
	*q = p; 
	*ret_val = hex;

	return 0; 
}

/*! \addtogroup registerAccessFunctions Register Access Functions
 @{*/

/*! Provides generic synchronous PHY register write functionality. It is the
 * responsibility of the system designer to provide the specific MDIO address 
 * pointer updates, etc. in order to accomplish this write operation. 
 * It will be assumed that the write has been completed by the time this 
 * function returns.*/
void AQ_USERPA_Register_Write
(
    /*! Uniquely identifies the system (if necessary). */
  unsigned int adapter,
    /*! Uniquely identifies the port within the system. */
  unsigned int PHY_ID,
    /*! The address of the MMD within the target PHY. */
  unsigned int MMD,
    /*! The 16-bit address of the PHY register being written. */
  unsigned int address,
    /*! The 16-bits of data to write to the specified PHY register. */
  unsigned int data
)
{
  /* TODO: insert here */
    int port = 0;
	int offset = 0;
	char cmd_buf[100] = "./stm32_uart_tool_v1.1 w 0x200F0302,0x0006,0x01,";

	if (adapter == 0 && PHY_ID == 0x08)
	{
		cmd_buf[32] = '3';
		cmd_buf[46] = '1';
		port = 1;
	}
	else if (adapter == 0 && PHY_ID == 0x09)
	{
		cmd_buf[32] = '3';
		cmd_buf[46] = '2';
		port = 2;
	}
	else if (adapter == 0 && PHY_ID == 0x0A)
	{
		cmd_buf[32] = '3';
		cmd_buf[46] = '3';
		port = 3;
	}
	else if (adapter == 0 && PHY_ID == 0x0B)
	{
		cmd_buf[32] = '3';
		cmd_buf[46] = '4';
		port = 4;
	}
	else if (adapter == 1 && PHY_ID == 0x08)
	{
		cmd_buf[32] = '3';
		cmd_buf[46] = '5';
		port = 5;
	}
	else if (adapter == 1 && PHY_ID == 0x09)
	{
		cmd_buf[32] = '3';
		cmd_buf[46] = '6';
		port = 6;
	}
	else if (adapter == 1 && PHY_ID == 0x0A)
	{
		cmd_buf[32] = '3';
		cmd_buf[46] = '7';
		port = 7;
	}
	else if (adapter == 1 && PHY_ID == 0x0B)
	{
		cmd_buf[32] = '3';
		cmd_buf[46] = '8';
		port = 8;
	}
	else if (adapter == 2 && PHY_ID == 0x08)
	{
		cmd_buf[32] = '2';
		cmd_buf[46] = '1';
		port = 9;
	}
	else if (adapter == 2 && PHY_ID == 0x09)
	{
		cmd_buf[32] = '2';
		cmd_buf[46] = '2';
		port = 10;
	}
	else if (adapter == 2 && PHY_ID == 0x0A)
	{
		cmd_buf[32] = '2';
		cmd_buf[46] = '3';
		port = 11;
	}
	else if (adapter == 2 && PHY_ID == 0x0B)
	{
		cmd_buf[32] = '2';
		cmd_buf[46] = '4';
		port = 12;
	}
	else if (adapter == 3 && PHY_ID == 0x08)
	{
		cmd_buf[32] = '2';
		cmd_buf[46] = '5';
		port = 13;
	}
	else if (adapter == 3 && PHY_ID == 0x09)
	{
		cmd_buf[32] = '2';
		cmd_buf[46] = '6';
		port = 14;
	}
	else if (adapter == 3 && PHY_ID == 0x0A)
	{
		cmd_buf[32] = '2';
		cmd_buf[46] = '7';
		port = 15;
	}
	else if (adapter == 3 && PHY_ID == 0x0B)
	{
		cmd_buf[32] = '2';
		cmd_buf[46] = '8';
		port = 16;
	}

	offset = strlen(cmd_buf);
	offset += sprintf(cmd_buf+offset, "0x%x,", MMD);
	offset += sprintf(cmd_buf+offset, "0x%x,", address&0xFF);
	offset += sprintf(cmd_buf+offset, "0x%x,", (address>>8)&0xFF);
	offset += sprintf(cmd_buf+offset, "0x%x,", data&0xFF);
	offset += sprintf(cmd_buf+offset, "0x%x", (data>>8)&0xFF);
	/*	
		printf("=====================\r\n");	
		printf("%x\r\n", MMD);
		printf("%x\r\n", address);
		printf("%s\r\n", cmd_buf);
		printf("=====================\r\n");	
	 */
/*	printf("%s",cmd_buf);*/

	FILE*   pResultStr  = NULL;
	char    szBuf[1024] = {0};

	/* 创建子进程，执行shell命令 */
	pResultStr = popen(cmd_buf, "r");
	if (NULL == pResultStr)
	{
		printf("popen faild. (%d, %s)\n",errno, strerror(errno));
		return -1;
	}

	/* 获取返回结果 */
	fread(szBuf, 1, sizeof(szBuf), pResultStr);

	/* 打印命令返回内容 */
/*	printf("Info: %s\n", szBuf);*/

	printf("write port=%2d MMD=%2x address=%4x val=%4x\r\n", port, MMD, address, data);
	/* 不要忘记关闭句柄 */
	pclose(pResultStr);
}

/*! Provides generic synchronous PHY register read functionality. It is the
 * responsibility of the system designer to provide the specific MDIO address 
 * pointer updates, etc. in order to accomplish this read operation.*/
unsigned int AQ_USERPA_Register_Read
(
    /*! Uniquely identifies the system (if necessary). */
  unsigned int adapter,
    /*! Uniquely identifies the port within the system. */
  unsigned int PHY_ID,
    /*! The address of the MMD within the target PHY. */
  unsigned int MMD,
    /*! The 16-bit address of the PHY register being read. */
  unsigned int address
)
{
    /* TODO insert here */
	int port = 0;
	int offset = 0;
	char cmd_buf[100] = "./stm32_uart_tool_v1.1 r 0x200F0302,0x0004,0x01,";

	if (adapter == 0 && PHY_ID == 0x08)
	{
		cmd_buf[32] = '3';
		cmd_buf[46] = '1';
		port = 1;
	}
	else if (adapter == 0 && PHY_ID == 0x09)
	{
		cmd_buf[32] = '3';
		cmd_buf[46] = '2';
		port = 2;
	}
	else if (adapter == 0 && PHY_ID == 0x0A)
	{
		cmd_buf[32] = '3';
		cmd_buf[46] = '3';
		port = 3;
	}
	else if (adapter == 0 && PHY_ID == 0x0B)
	{
		cmd_buf[32] = '3';
		cmd_buf[46] = '4';
		port = 4;
	}
	else if (adapter == 1 && PHY_ID == 0x08)
	{
		cmd_buf[32] = '3';
		cmd_buf[46] = '5';
		port = 5;
	}
	else if (adapter == 1 && PHY_ID == 0x09)
	{
		cmd_buf[32] = '3';
		cmd_buf[46] = '6';
		port = 6;
	}
	else if (adapter == 1 && PHY_ID == 0x0A)
	{
		cmd_buf[32] = '3';
		cmd_buf[46] = '7';
		port = 7;
	}
	else if (adapter == 1 && PHY_ID == 0x0B)
	{
		cmd_buf[32] = '3';
		cmd_buf[46] = '8';
		port = 8;
	}
	else if (adapter == 2 && PHY_ID == 0x08)
	{
		cmd_buf[32] = '2';
		cmd_buf[46] = '1';
		port = 9;
	}
	else if (adapter == 2 && PHY_ID == 0x09)
	{
		cmd_buf[32] = '2';
		cmd_buf[46] = '2';
		port = 10;
	}
	else if (adapter == 2 && PHY_ID == 0x0A)
	{
		cmd_buf[32] = '2';
		cmd_buf[46] = '3';
		port = 11;
	}
	else if (adapter == 2 && PHY_ID == 0x0B)
	{
		cmd_buf[32] = '2';
		cmd_buf[46] = '4';
		port = 12;
	}
	else if (adapter == 3 && PHY_ID == 0x08)
	{
		cmd_buf[32] = '2';
		cmd_buf[46] = '5';
		port = 13;
	}
	else if (adapter == 3 && PHY_ID == 0x09)
	{
		cmd_buf[32] = '2';
		cmd_buf[46] = '6';
		port = 14;
	}
	else if (adapter == 3 && PHY_ID == 0x0A)
	{
		cmd_buf[32] = '2';
		cmd_buf[46] = '7';
		port = 15;
	}
	else if (adapter == 3 && PHY_ID == 0x0B)
	{
		cmd_buf[32] = '2';
		cmd_buf[46] = '8';
		port = 16;
	}

	offset = strlen(cmd_buf);
	offset += sprintf(cmd_buf+offset, "0x%x,", MMD);
	offset += sprintf(cmd_buf+offset, "0x%x,", address&0xFF);
	offset += sprintf(cmd_buf+offset, "0x%x", (address>>8)&0xFF);
	
	FILE*   pResultStr  = NULL;
	char    szBuf[1024] = {0};

	/* 创建子进程，执行shell命令 */
	pResultStr = popen(cmd_buf, "r");
	if (NULL == pResultStr)
	{
		printf("popen faild. (%d, %s)\n",errno, strerror(errno));
		return -1;
	}

	/* 获取返回结果 */
	fread(szBuf, 1, sizeof(szBuf), pResultStr); 
	/* 打印命令返回内容 */
    /*	printf("Info: %s\n", szBuf);*/

	/* 不要忘记关闭句柄 */
	pclose(pResultStr);

	int tag,len,val,val1,val2;

	char *pszBuf = szBuf;

	ascii2hex(&pszBuf, &tag);
	ascii2hex(&pszBuf, &len);
	ascii2hex(&pszBuf, &val1);
	ascii2hex(&pszBuf, &val2);
 	val = (val2<<8)+val1;	 

	printf("read  port=%2d MMD=%2x address=%4x val=%4x\r\n", port, MMD, address, val);
	return val;
}

/*! Specifies the names of each of the adapters exposed by the server.
 * The number of adapter name strings specified in the initializer statement 
 * much match AQ_USERPA_NUM_ADAPTERS. */
char AQ_USERPA_AdapterNamesBuffer[AQ_USERPA_NUM_ADAPTERS][AQ_USERPA_MAX_ADAPTER_NAME_LENGTH+1] = 
    {"P1-4", 
     "P5-8", 
     "P9-12",
     "P13-P16"};

/*@}*/

#ifdef __cplusplus
  }
#endif

